#include "CLink/Router/BaseRouteHandler.h"
#include "CLink/Utils/StringUtils.h"
#include <Poco/Net/HTMLForm.h>

#include <Poco/URI.h>
#include <sstream>

namespace CLink
{
namespace Router
{

BaseRouteHandler::BaseRouteHandler(const std::string &path, const std::string &method, int priority)
    : m_path(path), m_method(method), m_priority(priority)
{
    buildPathRegex();
}

bool BaseRouteHandler::matches(const RequestContext &context) const
{
    const auto &request = context.request;
    // 检查HTTP方法是否匹配
    if (m_method != request.getMethod())
    {
        return false;
    }

    // 获取请求路径
    Poco::URI uri(request.getURI());
    std::string path = uri.getPath();

    // 使用正则表达式匹配路径
    std::smatch matches;
    return std::regex_match(path, matches, m_pathRegex);
}

int BaseRouteHandler::getPriority() const
{
    return m_priority;
}

BaseRouteHandler &BaseRouteHandler::addParam(const RouteParam &param)
{
    m_params.push_back(param);
    buildPathRegex();
    return *this;
}

BaseRouteHandler &BaseRouteHandler::setPriority(int priority)
{
    m_priority = priority;
    return *this;
}

const std::string &BaseRouteHandler::getPath() const
{
    return m_path;
}

const std::string &BaseRouteHandler::getMethod() const
{
    return m_method;
}

std::map<std::string, std::string> BaseRouteHandler::extractDynamicParams(
    const RequestContext &context) const
{
    std::map<std::string, std::string> params;

    const auto &request = context.request;
    // 获取请求路径
    Poco::URI uri(request.getURI());
    std::string path = uri.getPath();

    // 使用正则表达式匹配路径
    std::smatch matches;
    if (std::regex_match(path, matches, m_pathRegex))
    {
        // 跳过第一个匹配项（整个字符串）
        for (size_t i = 1; i < matches.size() && i - 1 < m_paramNames.size(); ++i)
        {
            params[m_paramNames[i - 1]] = matches[i].str();
        }
    }

    return params;
}


std::map<std::string, std::string> BaseRouteHandler::extractQueryParams(
    const RequestContext& context) const
{
    std::map<std::string, std::string> params;

    const auto& request = context.request;
    Poco::Net::HTMLForm form(request);

    // 提取所有查询参数
    if (m_queryParams.empty())
    {
        for (const auto& pair : form)
        {
            params[pair.first] = pair.second;
        }
        return params;
    }
    else
    {
        for (const auto& param : m_queryParams)
        {
            if (form.has(param.name))
            {
                params[param.name] = form.get(param.name);
            }
        }
    }

    return params;
}


void BaseRouteHandler::buildPathRegex()
{
    // 将路径模板转换为正则表达式
    std::string regexStr = m_path;
    m_paramNames.clear();

    // 替换路径参数占位符为正则表达式捕获组
    size_t pos = 0;
    while ((pos = regexStr.find(":", pos)) != std::string::npos)
    {
        size_t start = pos + 1;
        size_t end = regexStr.find_first_of("/?#", start);
        if (end == std::string::npos)
        {
            end = regexStr.length();
        }

        std::string paramName = regexStr.substr(start, end - start);
        m_paramNames.push_back(paramName);

        // 查找参数定义
        RouteParamType paramType = RouteParamType::STRING;
        std::string pattern;
        for (const auto &param : m_params)
        {
            if (param.name == paramName)
            {
                paramType = param.type;
                pattern = param.pattern;
                break;
            }
        }

        // 如果没有提供自定义模式，使用默认模式
        if (pattern.empty())
        {
            pattern = getParamPattern(paramType);
        }

        // 替换参数占位符为正则表达式捕获组
        std::string replacement = "(" + pattern + ")";
        regexStr.replace(pos, end - pos, replacement);
        pos += replacement.length();
    }

    // 转义正则表达式特殊字符
    /* CLink::Utils::StringUtils strUtils(regexStr);
        strUtils.replace(".", "\\.");
        strUtils.replace("*", "\\*");
        strUtils.replace("+", "\\+");
        strUtils.replace("?", "\\?");
        strUtils.replace("|", "\\|");
        strUtils.replace("(", "\\(");
        strUtils.replace(")", "\\)");
        strUtils.replace("[", "\\[");
        strUtils.replace("]", "\\]");
        strUtils.replace("{", "\\{");
        strUtils.replace("}", "\\}");
        strUtils.replace("^", "\\^");
        strUtils.replace("$", "\\$");
        regexStr = strUtils.toString();*/

    // 确保路径以 ^ 开头和 $ 结尾，以匹配整个路径
    if (regexStr[0] != '^')
    {
        regexStr = "^" + regexStr;
    }
    if (regexStr[regexStr.length() - 1] != '$')
    {
        regexStr += "$";
    }

    // 编译正则表达式
    m_pathRegex = std::regex(regexStr);
}

std::string BaseRouteHandler::getParamPattern(RouteParamType type) const
{
    switch (type)
    {
    case RouteParamType::INTEGER:
        return "[0-9]+";
    case RouteParamType::FLOAT:
        return "[0-9]+(\\.[0-9]+)?";
    case RouteParamType::BOOLEAN:
        return "(true|false|0|1)";
    case RouteParamType::REGEX:
        return ".*";
    case RouteParamType::STRING:
    default:
        return "[^/]+";
    }
}

bool BaseRouteHandler::validateQueryParams(const RequestContext& context) const
{
    const auto& request = context.request;
    Poco::Net::HTMLForm form(request);

    // 检查所有必需的查询参数
    if (!m_queryParams.empty())
    {
        for (const auto& param : m_queryParams)
        {
            if (param.required && !form.has(param.name))
            {
                return false;
            }

            if (form.has(param.name) && !param.pattern.empty())
            {
                std::string value = form.get(param.name);
                std::regex pattern(param.pattern);
                if (!std::regex_match(value, pattern))
                {
                    return false;
                }
            }
        }
    }
    else
    {
        for (const auto& pair : form)
        {
            // 如果没有定义查询参数，则不进行验证
            if (pair.first.empty() || pair.second.empty())
            {
                return false;
            }
        }
    }

    return true;
}


std::map<std::string, std::string> BaseRouteHandler::extractFormParams(const RequestContext& context) const
{
	std::map<std::string, std::string> params;
    const auto& request = context.request;
    Poco::Net::HTMLForm form(request, const_cast<Poco::Net::HTTPServerRequest&>(request).stream());

    for (const auto& pair : form)
    {
        params.insert(pair);
    }

    return params;
}

BaseRouteHandler& BaseRouteHandler::addQueryParam(const std::string& name,
    bool required,
    const std::string& pattern)
{
    m_queryParams.push_back(RouteParam(name,
        pattern.empty() ? RouteParamType::STRING : RouteParamType::REGEX,
        required,
        pattern));
    return *this;
}

BaseRouteHandler& BaseRouteHandler::addQueryParam(const std::vector<RouteParam>& query)
{
    for (const auto& param : query)
    {
        m_queryParams.push_back(param);
    }
    return *this;
}

} // namespace Router
} // namespace CLink